home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
libgutil
/
colormod.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
7KB
|
393 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* colormod -
* Define some transforms between different color models.
*
*
* Henry Moreton and Paul Haeberli - 1984
*
* exports
*
void irgb_to_rgb(ir,ig,ib,r,g,b)
void cmy_to_rgb(c,m,y,r,g,b)
void hls_to_rgb(h,l,s,r,g,b)
void hsv_to_rgb(h,s,v,r,g,b)
void hsb_to_rgb(h,s,v,r,g,b)
void yiq_to_rgb(y,i,q,r,g,b)
void rgb_to_rgb(fr,fg,fb,tr,tg,tb)
void rgb_to_cmy(r,g,b,c,m,y)
void rgb_to_irgb(r,g,b,ir,ig,ib)
void rgb_to_hls(r,g,b,h,l,s)
void rgb_to_hsv(r,g,b,lh,ls,lv)
void rgb_to_hsb(r,g,b,lh,ls,lv)
void rgb_to_yiq(r,g,b,y,i,q)
void setcolorsys(sys)
int getcolorsys(sys)
void torgb(r,g,b,tr,tg,tb)
void fromrgb(r,g,b,tr,tg,tb)
void rgbcomplement(r,g,b,cr,cg,cb)
*
*/
#include "math.h"
#include "stdio.h"
#include "colormod.h"
void rgb_to_rgb();
static void (*tofunc)() = rgb_to_rgb;
static void (*fromfunc)() = rgb_to_rgb;
static int colorsys = COLORSYS_RGB;
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
/*
* Convert FROM various formats TO rgb.
*
*
*/
void irgb_to_rgb(ir,ig,ib,r,g,b)
int ir, ig, ib;
float *r, *g, *b;
{
*r = ir/255.0;
*g = ig/255.0;
*b = ib/255.0;
}
void cmy_to_rgb(c,m,y,r,g,b)
float c, m, y;
float *r, *g, *b;
{
*r = 1.0-c;
*g = 1.0-m;
*b = 1.0-y;
}
static float value(n1, n2, hue)
float n1, n2, hue;
{
if (hue>360)
hue-=360;
if (hue<0)
hue+=360;
if (hue<60)
return(n1+(n2-n1)*(hue/60.0));
if (hue<180)
return(n2);
if (hue<240)
return(n1+(n2-n1)*((240-hue)/60.0));
return n1;
}
void hls_to_rgb(h,l,s,r,g,b)
float h, l, s;
float *r, *g, *b;
{
float m1, m2;
h *= 360.0;
if (l<=0.5)
m2 = l*(1.0+s);
else
m2 = l+s-l*s;
m1 = 2*l-m2;
if (s==0)
*r = *g = *b = l;
else {
*r = value(m1,m2,h+120.0);
*g = value(m1,m2,h);
*b = value(m1,m2,h-120.0);
}
}
void hsv_to_rgb(h,s,v,r,g,b)
float h, s, v;
float *r, *g, *b;
{
int i;
float f, p, q, t;
h *= 360.0;
if (s==0) {
*r = v;
*g = v;
*b = v;
} else {
if (h==360)
h = 0;
h /= 60;
i = ffloor(h);
f = h - i;
p = v*(1.0-s);
q = v*(1.0-(s*f));
t = v*(1.0-(s*(1.0-f)));
switch (i) {
case 0 :
*r = v;
*g = t;
*b = p;
break;
case 1 :
*r = q;
*g = v;
*b = p;
break;
case 2 :
*r = p;
*g = v;
*b = t;
break;
case 3 :
*r = p;
*g = q;
*b = v;
break;
case 4 :
*r = t;
*g = p;
*b = v;
break;
case 5 :
*r = v;
*g = p;
*b = q;
break;
}
}
}
void hsb_to_rgb(h,s,v,r,g,b)
float h, s, v;
float *r, *g, *b;
{
hsv_to_rgb(h,s,v,r,g,b);
}
void yiq_to_rgb(y,i,q,r,g,b)
float y, i, q;
float *r, *g, *b;
{
*r = y + 0.948262*i + 0.624013*q;
*g = y + -0.276066*i + -0.63981*q;
*b = y + -1.10545*i + 1.72986*q;
}
/*
* Convert FROM rgb TO rgb.
*
*
*/
void rgb_to_rgb(fr,fg,fb,tr,tg,tb)
float fr, fg, fb;
float *tr, *tg, *tb;
{
*tr = fr;
*tg = fg;
*tb = fb;
}
/*
* Convert TO various formats FROM rgb.
*
*
*/
void rgb_to_cmy(r,g,b,c,m,y)
float r, g, b;
float *c, *m, *y;
{
*c = 1.0-r;
*m = 1.0-g;
*y = 1.0-b;
}
void rgb_to_irgb(r,g,b,ir,ig,ib)
float r, g, b;
int *ir, *ig, *ib;
{
*ir = (r*255.0)+0.5;
*ig = (g*255.0)+0.5;
*ib = (b*255.0)+0.5;
}
void rgb_to_hls(r,g,b,h,l,s)
float r, g, b;
float *h, *l, *s;
{
float rc, gc, bc;
float maxcol, mincol, cdelta;
maxcol = MAX(r,MAX(g,b));
mincol = MIN(r,MIN(g,b));
*l = (mincol+maxcol)/2; /* lightness */
if (maxcol==mincol) { /* achromatic case */
*s = 0; /* *h is undefined in the achromatic case */
*h = 0;
} else {
if (*l<=0.5)
*s = (maxcol-mincol)/(maxcol+mincol);
else
*s = (maxcol-mincol)/(2-maxcol-mincol);
/* find hue */
cdelta = maxcol-mincol;
rc = (maxcol-r)/cdelta;
gc = (maxcol-g)/cdelta;
bc = (maxcol-b)/cdelta;
if (r==maxcol)
*h = bc-gc;
else if (g==maxcol)
*h = 2+rc-bc;
else
*h = 4+gc-rc;
*h *= 60.0;
if (*h<0.0)
*h += 360.0;
*h /= 360.0;
}
}
void rgb_to_hsv(r,g,b,lh,ls,lv)
float r, g, b;
float *lh, *ls, *lv;
{
float h, s, v;
float cmax, cmin, cdelta;
float rc, gc, bc;
/* find the cmax and cmin of r g b */
cmax = r;
cmin = r;
cmax = (g>cmax ? g:cmax);
cmin = (g<cmin ? g:cmin);
cmax = (b>cmax ? b:cmax);
cmin = (b<cmin ? b:cmin);
v = cmax; /* value */
if (cmax!=0.0)
s = (cmax - cmin)/cmax;
else {
s = 0.0;
h = 0.0;
}
if (s == 0.0)
h = -1.0;
else {
cdelta = cmax-cmin;
rc = (cmax-r)/cdelta;
gc = (cmax-g)/cdelta;
bc = (cmax-b)/cdelta;
if (r==cmax)
h = bc-gc;
else
if (g==cmax)
h = 2.0+rc-bc;
else
h = 4.0+gc-rc;
h = h*60.0;
if (h<0.0)
h += 360.0;
}
*ls = s;
*lh = h/360.0;
*lv = v;
}
void rgb_to_hsb(r,g,b,lh,ls,lv)
float r, g, b;
float *lh, *ls, *lv;
{
rgb_to_hsv(r,g,b,lh,ls,lv);
}
void rgb_to_yiq(r,g,b,y,i,q)
float r, g, b;
float *y, *i, *q;
{
*y = (0.30*r+0.59*g+0.11*b);
*i = (0.60 *r-0.28*g-0.32*b);
*q = (0.21*r-0.52*g+0.31*b);
}
void setcolorsys(sys)
{
switch(sys) {
case COLORSYS_RGB:
tofunc = rgb_to_rgb;
fromfunc = rgb_to_rgb;
colorsys = sys;
break;
case COLORSYS_CMY:
tofunc = cmy_to_rgb;
fromfunc = rgb_to_cmy;
colorsys = sys;
break;
case COLORSYS_HSV:
tofunc = hsv_to_rgb;
fromfunc = rgb_to_hsv;
colorsys = sys;
break;
case COLORSYS_HLS:
tofunc = hls_to_rgb;
fromfunc = rgb_to_hls;
colorsys = sys;
break;
case COLORSYS_YIQ:
tofunc = yiq_to_rgb;
fromfunc = rgb_to_yiq;
colorsys = sys;
break;
default:
fprintf(stderr,"bad color system no %d\n",sys);
break;
}
}
int getcolorsys(sys)
{
return colorsys;
}
void torgb(r,g,b,tr,tg,tb)
float r, g, b;
float *tr, *tg, *tb;
{
tofunc(r,g,b,tr,tg,tb);
}
void fromrgb(r,g,b,tr,tg,tb)
float r, g, b;
float *tr, *tg, *tb;
{
fromfunc(r,g,b,tr,tg,tb);
}
void rgbcomplement(r,g,b,cr,cg,cb)
float r, g, b;
float *cr, *cg, *cb;
{
float h, s, v;
rgb_to_hsv(r,g,b,&h,&s,&v);
v = v+0.5;
if(v>1.0);
v -= 1.0;
hsv_to_rgb(h,s,v,cr,cg,cb);
}